package com.springboot.seckill.service.impl;

import com.springboot.seckill.dataobject.UserDO;
import com.springboot.seckill.dataobject.UserPasswordDO;
import com.springboot.seckill.error.BusinessException;
import com.springboot.seckill.error.EmBusinessError;
import com.springboot.seckill.mapper.UserDOMapper;
import com.springboot.seckill.mapper.UserPasswordDOMapper;
import com.springboot.seckill.service.UserService;
import com.springboot.seckill.service.model.UserModel;
import com.springboot.seckill.validator.ValidationResult;
import com.springboot.seckill.validator.ValidatorImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author: HuangDekai
 * @Date: 2022/3/7 18:05
 * @Version: 1.0
 * @since: jdk11
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDOMapper userDOMapper;
    @Autowired
    private UserPasswordDOMapper userPasswordDOMapper;
    @Autowired
    private ValidatorImpl validator;

    /**
     * 调用UserDOMapper获取对应用户的DataObject
     *
     * @param id 用户数据库主键id
     */
    @Override
    public UserModel getUserById(Integer id) {
        UserDO userDO = userDOMapper.selectByPrimaryKey(id);
        if (userDO == null) {
            return null;
        }

        UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(id);
        return convertFromDataObject(userDO, userPasswordDO);
    }

    /**
     * 实现userDO和userPasswordDO合成userModel
     * @param userDO userDo
     * @param userPasswordDO userPasswordDO
     * @return userModel
     */
    private UserModel convertFromDataObject(UserDO userDO, UserPasswordDO userPasswordDO) {
        if (userDO == null) {
            return null;
        }

        UserModel userModel = new UserModel();
        BeanUtils.copyProperties(userDO, userModel);

        if (userPasswordDO != null) {
            userModel.setEncrptPassword(userPasswordDO.getEncrptPassword());
        }

        return userModel;
    }

    /**
     * 对应用户注册的流程
     *
     * @param userModel userModel
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(UserModel userModel) throws BusinessException {
        if (userModel == null) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
        }
        ValidationResult result = validator.validate(userModel);
        if (result.isHasErrors()) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, result.getErrMsg());
        }

        //实现model->dataObject
        UserDO userDO = convertFromModel(userModel);
        /*
        * insertSelective对比insert的区别是:
        *   insertSelective会先判断对应字段是否为null, 如果是, 会跳过不insert该字段, 则数据库会使用sql表之前设置好的默认值
        * */
        try {
            userDOMapper.insertSelective(userDO);
        } catch (DuplicateKeyException e) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "手机账号已注册");
        }

        userModel.setId(userDO.getId());

        UserPasswordDO userPasswordDO = convertPasswordFromModel(userModel);
        userPasswordDOMapper.insertSelective(userPasswordDO);

    }

    /**
     * 将userModel分解给userDO
     * @param userModel userModel
     * @return userDO
     */
    private UserDO convertFromModel(UserModel userModel) {
        if (userModel == null) {
            return null;
        }
        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(userModel, userDO);
        return userDO;
    }

    /**
     * 将userModel分解给userPasswordDO
     * @param userModel userModel
     * @return userPasswordDO
     */
    private  UserPasswordDO convertPasswordFromModel(UserModel userModel) {
        if (userModel == null) {
            return  null;
        }
        UserPasswordDO userPasswordDO = new UserPasswordDO();
        userPasswordDO.setEncrptPassword(userModel.getEncrptPassword());
        userPasswordDO.setUserId(userModel.getId());
        return userPasswordDO;
    }

    /**
     * 验证登录时的telphone和passowrd(此时应该已经MD5加密)
     *
     * @param telphone       telphone, 手机号
     * @param encrptPassword encrptPassword, MD5加密过的密码
     */
    @Override
    public UserModel validateLogin(String telphone, String encrptPassword) throws BusinessException {
        //通过用户手机号获取用户信息
        UserDO userDO = userDOMapper.selectByTelphone(telphone);
        if (userDO == null) {
            throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL);
        }
        UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId());
        UserModel userModel = convertFromDataObject(userDO, userPasswordDO);

        //比对用户信息内加密的密码是否和传输进来的密码相匹配
        if (!StringUtils.equals(encrptPassword, userModel.getEncrptPassword())) {
            throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL);
        }
        return userModel;
    }
}
